前面 28 天依主題排下來,有幾個常出現在正解裡的服務一直沒有輪到:執行容器的 ECS 與 Fargate、S3 的存取控制、不開 port 就能登入 EC2 的 Session Manager,以及把整套環境寫成範本的 CloudFormation。它們各自都不難,但題目寫出「不想管理伺服器的容器」「bucket 必須保持私有」「不能開放 inbound port」「在另一個 Region 建立相同的環境」時,答案幾乎就是它們。
這篇用一個網站上線的過程把四者串起來:應用程式改成容器部署,使用者上傳的檔案放進 S3,維運人員要登入幾台還在 EC2 上的舊系統,最後整套環境要能在另一個 Region 重新建立。
用途:把打包好的容器部署到 AWS,維持指定的數量持續運作,故障時自動補上。
容器把應用程式和它需要的函式庫、設定打包成一個映像檔(image),在任何裝了容器執行環境的機器上都以相同方式執行。映像檔存放在 Amazon ECR(Elastic Container Registry),Amazon ECS(Elastic Container Service)負責決定容器在哪裡執行、執行幾份。
ECS 的三個基本名詞:

task 要執行在某種運算資源上,ECS 提供兩種啟動模式(launch type):
| EC2 launch type | Fargate | |
|---|---|---|
| task 執行在 | 自己帳號中的 EC2 instance | AWS 管理的運算資源,看不到底層機器 |
| 需要管理 | instance 的類型、數量、修補,以及容量夠不夠放下所有 task | 只定義每個 task 的 CPU 與記憶體 |
| 計費 | 依 EC2 instance | 依 task 使用的 vCPU 與記憶體,以秒計費(最少 1 分鐘) |
| 適合 | 需要 GPU 等特定 instance 類型、以 Reserved Instance 壓低長期成本 | 不想管理伺服器、流量起伏大 |
ECS 的 task 會用到兩個 IAM role,題目常拿它們互相替換:
另一個容器服務是 Amazon EKS(Elastic Kubernetes Service),提供受管的 Kubernetes。Kubernetes 是開源的容器管理平台,如果團隊已經在使用 Kubernetes,或要把地端的 Kubernetes 工作負載搬上 AWS,選 EKS;沒有這個前提時,ECS 的設定比較簡單。EKS 也可以使用 Fargate 執行。
| 題目寫的 | 選擇 |
|---|---|
| 執行容器,不想管理伺服器的修補與容量 | ECS on Fargate |
| 需要 GPU 或特定的 instance 類型 | ECS 的 EC2 launch type |
| 已經使用 Kubernetes、遷移既有的 Kubernetes 工作負載 | EKS |
| 存放與管理容器映像檔 | ECR |
| 容器中的程式要存取 S3、DynamoDB | task role |
| 拉取 ECR 映像檔、寫入 CloudWatch Logs 失敗 | task execution role |
| 單次執行超過 15 分鐘的工作 | ECS on Fargate(Lambda 的執行時間上限是 15 分鐘) |
常見的錯誤選項:把程式需要的權限加到 task execution role;把 IAM user 的 access key 存成容器的環境變數;題目說不想管理伺服器,選項卻用 EC2 launch type 或自己在 EC2 上安裝 Docker。
用途:決定誰能讀寫 bucket 中的物件,以及如何在 bucket 不公開的情況下,讓外部使用者上傳或下載單一檔案。
S3 的 bucket 與物件預設都是私有的,只有擁有者帳號中被授權的身分能存取。一個請求能不能成功,依序經過三道判斷:

Deny 符合這個請求,請求就被拒絕,其他 Allow 都無效bucket policy 常見的用途除了開放跨帳號存取,還有加上條件限制請求:以 aws:SecureTransport 拒絕不是 HTTPS 的請求、以 aws:SourceVpce 只允許經由特定 VPC endpoint 的請求、只允許特定 CloudFront distribution 讀取。
讓 App 的使用者上傳照片,最直接的做法是讓檔案先傳到後端,再由後端寫進 S3,但檔案很大時後端的頻寬與運算會先撐不住。pre-signed URL 讓檔案直接傳到 S3:後端以自己的憑證為「某個物件的某個操作」(例如對 uploads/user-123/photo.jpg 執行 PUT)產生一個帶簽章與到期時間的網址,任何拿到網址的人都能在到期前執行這個操作,bucket 本身仍是私有的。
這個網址的權限來自產生它的身分:產生者本身沒有 s3:PutObject 權限,網址也無法上傳。以 IAM user 的長期憑證產生時,有效期最長 7 天;以 IAM role 的臨時憑證產生時,憑證過期網址也隨之失效。
瀏覽器有同源政策(same-origin policy):https://www.example.com 頁面中的 JavaScript,預設不能讀取另一個網域(例如 bucket 的網址)回傳的內容。網頁直接以 JavaScript 存取 S3 時,要在 bucket 上設定 CORS(cross-origin resource sharing),列出允許的來源網域與 HTTP 方法,瀏覽器才會放行。CORS 只決定瀏覽器放不放行,不提供任何權限,請求本身仍要通過 policy 或使用 pre-signed URL。
一個存放共用資料集的 bucket 被很多團隊與應用程式使用時,所有規則都寫在同一份 bucket policy 中,很快就難以維護。S3 Access Points 為同一個 bucket 建立多個存取點,每個存取點有自己的名稱與 policy,例如分析團隊的存取點只能讀取 sales/;存取點也可以限制只接受來自特定 VPC 的請求。
| 題目寫的 | 選擇 |
|---|---|
| 防止任何物件被意外公開 | 在帳號層級開啟 Block Public Access |
| 讓另一個帳號存取 bucket | bucket policy 允許對方帳號,對方的 IAM policy 也允許 |
| 只允許 HTTPS、只允許經由 VPC endpoint 的請求 | bucket policy 搭配 aws:SecureTransport、aws:SourceVpce 條件 |
| 外部使用者暫時上傳或下載單一物件,bucket 保持私有 | pre-signed URL |
| 網頁的 JavaScript 存取 S3 被瀏覽器擋下 | 在 bucket 上設定 CORS |
| 多個團隊共用一個 bucket,各自需要不同的權限 | S3 Access Points |
常見的錯誤選項:為了讓使用者上傳,開放 bucket 的公開寫入,再以前綴限制路徑;以 CORS 解決 AccessDenied,CORS 不提供權限;大檔案經由 API Gateway 上傳,API Gateway 的請求大小上限是 10 MB。
用途:維運人員登入 EC2 執行指令,不需要 bastion host 與 SSH 金鑰,也不開放任何 inbound port。
登入私有 subnet 中 EC2 的傳統做法,是在 public subnet 放一台 bastion host(跳板機),開放 22 port 讓維運人員以 SSH 連入,再從它跳到其他 instance。這帶來三個問題:22 port 暴露在外、SSH 金鑰要發放與輪替、登入後執行了哪些指令沒有紀錄。

AWS Systems Manager Session Manager 把連線方向反過來。instance 上的 SSM Agent(Amazon Linux、Windows Server 等 AWS 提供的 AMI 已預先安裝)主動以 HTTPS 向 Systems Manager 服務建立向外的連線;維運人員從 console 或 CLI 開啟 session 時,指令經由這條連線送到 instance。因為連線是 instance 主動發起的,security group 不需要任何 inbound 規則,也不需要 bastion host 與 SSH 金鑰。
使用 Session Manager 需要三個條件:
AmazonSSMManagedInstanceCore 這類讓 Agent 與 Systems Manager 溝通的權限誰可以登入哪些 instance 由 IAM policy 決定(例如只允許登入特定 tag 的 instance)。每次開啟 session 都會記錄在 CloudTrail;session 中執行的指令與輸出,可以設定寫入 S3 或 CloudWatch Logs 供稽核。
Systems Manager 還有其他常出現在選項中的功能:Run Command 對大量 instance 一次執行同一個指令,Patch Manager 自動修補作業系統,Parameter Store 存放設定值與密碼。
| 題目寫的 | 選擇 |
|---|---|
| 不開 inbound port、不管理 SSH 金鑰,登入 EC2 | Session Manager |
| 記錄每次 session 中執行的指令與輸出 | Session Manager 的 session 記錄,寫入 S3 或 CloudWatch Logs |
| 私有 subnet 沒有 NAT gateway,仍要使用 Session Manager | Systems Manager 的 interface VPC endpoint |
| 在數百台 instance 上執行同一個指令 | Run Command |
| 自動修補作業系統 | Patch Manager |
常見的錯誤選項:保留 bastion host,只把來源限制為公司的 IP(22 port 仍然開著);以 VPC Flow Logs 記錄登入後執行的指令,Flow Logs 只記錄 IP、port 這類流量資訊;以 CloudTrail 記錄 instance 內執行的指令,CloudTrail 記錄的是 AWS API 呼叫。
用途:用一份範本描述 VPC、EC2、資料庫等資源,自動建立、更新與刪除,讓相同的環境可以在其他 Region 或帳號重複建立。
以 console 逐一點選建立資源,很難保證第二次建立的環境和第一次一樣,也無法追蹤誰改了什麼。AWS CloudFormation 屬於 IaC(infrastructure as code):在 YAML 或 JSON 格式的範本(template)中宣告需要哪些資源與設定,CloudFormation 依資源之間的相依關係決定建立順序,把這組資源當作一個 stack 管理。範本可以放進版本控制,環境的每次變更都有紀錄。
stack 的生命週期中有幾個常考的功能:
DeletionPolicy 為 Retain 或 Snapshot,刪除時保留資源或先建立快照CloudFormation 建立資源時,預設使用執行者自己的權限,所以開發人員要部署含有 IAM role 的範本,就必須直接擁有建立 IAM role 的權限,也能繞過範本自己在 console 建立。指定 service role 後,CloudFormation 改用這個 role 的權限建立資源;開發人員只需要 CloudFormation 的權限,以及把這個 role 交給 CloudFormation 的 iam:PassRole 權限,就只能透過 stack 建立資源。
| 題目寫的 | 選擇 |
|---|---|
| 在其他 Region 或環境快速重建相同的架構 | CloudFormation 範本 |
| 部署到 Organizations 中的多個帳號與 Region | StackSets |
| 更新前先確認會修改或取代哪些資源 | change set |
| 找出被手動修改的資源 | drift detection |
| 刪除 stack 時保留資料庫 | DeletionPolicy 設為 Retain 或 Snapshot |
| 開發人員只能透過 CloudFormation 建立資源 | service role + iam:PassRole |
常見的錯誤選項:撰寫腳本或操作手冊,在每個 Region 手動逐一建立資源;以 drift detection 找出 stack 以外的資源,它只檢查 stack 中的資源。
另外幾個缺口是把地端資料搬上 AWS 的服務,題目通常只考「哪個情境用哪個」:
| 題目寫的 | 選擇 |
|---|---|
| 地端應用程式以 NFS/SMB 存取 S3,常用檔案留在地端快取 | AWS Storage Gateway(S3 File Gateway) |
| 地端備份軟體以虛擬磁帶備份到 AWS | AWS Storage Gateway(Tape Gateway) |
| 數十 TB 以上的資料、網路頻寬不足,以實體裝置寄送 | AWS Snowball Edge |
| 經由網路把地端 NFS/SMB 的檔案搬移或定期同步到 S3、EFS、FSx | AWS DataSync |
摘要:執行容器、不想管理伺服器選 ECS on Fargate,需要 GPU 或 Reserved Instance 選 EC2 launch type,已使用 Kubernetes 選 EKS;容器中的程式用 task role,拉取映像檔與寫日誌用 task execution role。S3 預設私有,Block Public Access 防止意外公開,跨帳號要 IAM policy 與 bucket policy 兩邊都允許,pre-signed URL 讓外部使用者在 bucket 私有的情況下存取單一物件,CORS 只決定瀏覽器放不放行。Session Manager 由 instance 主動向外連線,不需要 inbound port、bastion host 與 SSH 金鑰,session 內容可以留存稽核。CloudFormation 以範本建立整套環境,change set 預覽變更,StackSets 部署到多帳號與多 Region,service role 讓開發人員只能透過 stack 建立資源。
某物流公司把訂單追蹤 API 打包成容器映像檔,存放在 Amazon ECR。API 需要持續運作,部分批次匯出的請求要執行 20 分鐘以上,白天與夜間的流量相差約 10 倍。維運團隊只有兩個人,不希望再管理任何伺服器的修補與容量規劃。
哪一個方案的維運負擔最低(LEAST operational overhead)?
某公司在 Amazon ECS 上以 Fargate 執行影像處理服務。task 能正常從私有的 Amazon ECR repository 拉取映像檔,日誌也有寫進 CloudWatch Logs。新版程式要把處理結果寫入一個 Amazon S3 bucket,部署後容器中的程式呼叫
PutObject時收到 AccessDenied 錯誤。公司的資安政策禁止在任何地方保存長期的 access key。
哪一個方案最安全(MOST secure)?
s3:PutObject 的 IAM role,在 task definition 中把它設定為 task roles3:PutObject 權限,再重新部署 services3:PutObject 權限的 IAM user,把 access key 存進 Secrets Manager,再注入為容器的環境變數Principal: "*" 搭配 aws:SourceVpce 條件,允許經由 S3 gateway endpoint 的所有寫入某相片沖印服務的行動 App 讓使用者上傳相片,每張 20–80 MB。目前相片先上傳到 EC2 上的後端 API,再由 API 轉存到 Amazon S3;促銷期間,後端的網路頻寬與 CPU 經常滿載。S3 bucket 必須保持私有,每位使用者只能上傳到自己的路徑。
哪一個方案最符合成本效益(MOST cost-effective)?
PutObject 寫入使用者的路徑uploads/ 前綴執行 s3:PutObject,App 依使用者 ID 組出路徑後直接上傳某公司在私有 subnet 中執行數十台 EC2 instance(Amazon Linux 2023),subnet 經由 NAT gateway 連上網際網路。目前維運人員先以 SSH 登入 public subnet 中的 bastion host,再跳到各台 instance。新的資安要求是:所有 instance 的 security group 不能有任何 inbound 規則、不再發放與輪替 SSH 金鑰,而且每次登入期間執行的指令與輸出都要保存一年供稽核。
哪兩項做法的組合最符合這些需求?(選擇兩項)
AmazonSSMManagedInstanceCore 的 instance profile,改以 Session Manager 登入並移除 bastion host某公司的開發人員以 AWS CloudFormation 部署各自負責的應用程式環境,範本中包含 IAM role、Lambda 函式與 DynamoDB 資料表。目前開發人員的 IAM policy 直接擁有建立這些資源的權限,資安團隊發現有人在 console 手動建立了未經審核的 IAM role。公司要求開發人員只能透過 CloudFormation 建立資源。
哪一個方案最符合這些需求,且遵循最小權限原則?
iam:PassRole 權限Fargate 由 AWS 管理執行 task 的運算資源,團隊只定義每個 task 的 CPU 與記憶體,不需要修補 instance 或規劃 cluster 的容量。ECS service 維持 task 持續運作並放在 ALB 後方,target tracking 依 CPU 使用率增減 task 數量,可以應付白天與夜間的流量差距;task 的執行時間沒有上限,20 分鐘以上的匯出請求也能完成。
A 能運作,但 EC2 launch type 的 instance 仍要自己修補與選擇類型,違反不想管理伺服器的要求。B 是無伺服器的做法,但 Lambda 單次執行最長 15 分鐘,20 分鐘以上的匯出請求會被中斷。D 的 managed node group 仍是帳號中的 EC2 instance,團隊還要學習與維護 Kubernetes,維運負擔比 ECS on Fargate 高。
task role 的權限交給容器中的程式使用,SDK 會自動取得這個 role 的臨時憑證,不需要保存任何 access key。這個 role 只允許對該 bucket 執行 s3:PutObject,權限剛好夠用。
B 是兩個 role 的混淆:task execution role 給 ECS 拉取映像檔、寫入日誌使用,容器中的程式拿不到它的權限,加了也仍是 AccessDenied。C 能運作,但 IAM user 的 access key 是長期憑證,違反資安政策。D 也能讓寫入成功,但 VPC 中任何經過這個 endpoint 的程式都能寫入 bucket,權限過大,不如只授權給這個 task 的 role 安全。
pre-signed URL 讓相片從 App 直接上傳到 S3,不再經過後端,後端只負責驗證使用者並產生網址,頻寬與 CPU 的負擔大幅降低,也不需要為促銷增加 instance。網址只能對指定的路徑執行 PUT,15 分鐘後失效,bucket 保持私有,使用者也無法寫入別人的路徑。
A 能撐住尖峰,但相片仍經過後端,要為大量上傳流量付出更多 instance 的費用,成本最高。B 有一個硬限制:API Gateway 的請求大小上限是 10 MB,20–80 MB 的相片無法經由它上傳。C 讓任何人都能寫入 uploads/,違反 bucket 必須私有的要求,App 自己組出的路徑也無法阻止使用者寫入別人的路徑。
A 讓 instance 能使用 Session Manager:SSM Agent 主動向外連到 Systems Manager(經由現有的 NAT gateway),維運人員以 IAM 權限開啟 session,security group 不需要 inbound 規則,也不需要 SSH 金鑰,bastion host 可以移除。B 把每次 session 中執行的指令與輸出寫入 S3,再以生命週期規則保存一年,滿足稽核要求(instance profile 也要加上寫入該 bucket 的權限)。
C 不需要 bastion host,但 instance 的 security group 仍要允許來自 endpoint 的 22 port,也仍要管理 SSH 的連線方式,違反不能有 inbound 規則的要求。D 的 22 port 仍然開著,CloudTrail 記錄的是 AWS API 呼叫,看不到登入後在 instance 中執行的指令。E 的 Flow Logs 只記錄 IP、port、位元組數這類流量資訊,無法記錄執行了哪些指令。
指定 service role 後,CloudFormation 以這個 role 的權限建立 IAM role、Lambda 函式與 DynamoDB 資料表,開發人員自己不再擁有這些權限,在 console 手動建立會被拒絕,只能透過 stack 建立。iam:PassRole 只允許把這一個 role 交給 CloudFormation,權限範圍最小。
A 只是事後補救,開發人員仍能手動建立資源;而且 drift detection 只檢查 stack 中的資源是否被修改,找不到不屬於任何 stack 的 IAM role。C 的 StackSets 用於把範本部署到多個帳號與 Region,和限制開發人員的權限無關。D 限制了開發人員建立的 IAM role 能擁有的權限,但他們仍能直接在 console 建立資源,不符合只能透過 CloudFormation 建立的要求。